﻿#pragma once
#include "AnyParser.h"
#include "GetpotParser.h"

class Configuration
{
public:
  bool HaveVariable(const std::string& name) const
  {
    return _container.HaveVariable(name) || _pot.HaveVariable(name);
  }
  void SetSection(const std::string& prefix) { _pot.SetSection(prefix); }
  bool HaveSection(const std::string& prefix)
  {
    return _pot.HaveSection(prefix);
  }

  template<typename T>
  void Set(const std::string& name, const T& value)
  {
    _container.Set(name, value);
  }

  void Set(int argc, char* argv[]) { _pot.Set(argc, argv); }
  void Set(std::istream& ss) { _pot.Set(ss); }
  void Set(const std::string& file) { _pot.Set(file); }


  template<typename T, typename std::enable_if<!std::is_pointer<T>::value>::type* = nullptr>
  T Get(const std::string& name) const
  {
    if (_container.HaveVariable(name) && _pot.HaveVariable(name))
    {
      console::Warning("两种Parser中都存在: ", name);
    }

    if (_container.HaveVariable(name))
    {
      return _container.Get<T>(name);
    }

    if (_pot.HaveVariable(name))
    {
      return _pot.Get<T>(name);
    }

    if constexpr (is_vector<T>::value)
    {
      return T{};
    }
    console::Error(name, "不存在");
  }

  template<typename T, typename std::enable_if<!std::is_pointer<T>::value>::type* = nullptr>
  T Get(const std::string& name, T&& default) const
  {
    if (_container.HaveVariable(name) && _pot.HaveVariable(name))
    {
      console::Warning("两种Parser中都存在: ", name);
    }

    if (_container.HaveVariable(name))
    {
      return _container.Get<T>(name);
    }

    if (_pot.HaveVariable(name))
    {
      return _pot.Get<T>(name);
    }

    return default;
  }

  template<typename T, typename std::enable_if<std::is_pointer<T>::value>::type* = nullptr>
  T Get(const std::string& name) const
  {
    T pointer = _container.Get<T>(name);
    if (pointer == nullptr)
      console::Error("空指针");

    return pointer;
  }

  GetpotParser& GetPotParser() { return _pot; }

private:
  AnyParser _container;
  GetpotParser _pot;
};
